"""
文件系统工具

这个工具展示了如何实现文件操作功能，
包括文件的读取、写入、创建和删除等操作。
"""

import os
import json
from pathlib import Path
from typing import Union, List, Dict, Any
from .base import Tool, ToolType


class FileSystemTool(Tool):
    """
    文件系统工具类
    
    提供安全的文件操作功能，包括读取、写入、创建和删除文件。
    这展示了如何实现带有安全控制的系统操作工具。
    """
    
    def __init__(self, base_path: str = ".", max_file_size: int = 10 * 1024 * 1024):  # 10MB
        super().__init__(
            name="filesystem",
            description="执行文件系统操作，如读取、写入、创建和删除文件",
            tool_type=ToolType.FILE_OPERATION
        )
        
        self.base_path = Path(base_path).resolve()
        self.max_file_size = max_file_size
        
        # 允许的文件扩展名（安全控制）
        self.allowed_extensions = {
            '.txt', '.md', '.json', '.csv', '.log', 
            '.py', '.js', '.html', '.css', '.xml',
            '.yaml', '.yml', '.ini', '.cfg'
        }
        
        # 禁止访问的目录
        self.forbidden_paths = {
            '/etc', '/usr', '/bin', '/sbin', '/var',
            'C:\\Windows', 'C:\\Program Files'
        }
    
    async def execute(self, operation: str, file_path: str, content: str = None, encoding: str = 'utf-8') -> str:
        """
        执行文件系统操作
        
        Args:
            operation: 操作类型 ('read', 'write', 'create', 'delete', 'list', 'exists')
            file_path: 文件路径
            content: 文件内容（写入和创建操作时需要）
            encoding: 文件编码，默认utf-8
            
        Returns:
            操作结果
        """
        
        if not operation or not file_path:
            return "错误: 操作类型和文件路径不能为空"
        
        operation = operation.lower().strip()
        
        try:
            # 安全检查
            safe_path = self._validate_path(file_path)
            if not safe_path:
                return f"错误: 文件路径不安全或不被允许: {file_path}"
            
            # 根据操作类型执行相应功能
            if operation == 'read':
                return await self._read_file(safe_path, encoding)
            elif operation == 'write':
                return await self._write_file(safe_path, content or "", encoding, overwrite=True)
            elif operation == 'create':
                return await self._write_file(safe_path, content or "", encoding, overwrite=False)
            elif operation == 'delete':
                return await self._delete_file(safe_path)
            elif operation == 'list':
                return await self._list_directory(safe_path)
            elif operation == 'exists':
                return await self._check_exists(safe_path)
            else:
                return f"错误: 不支持的操作类型: {operation}"
                
        except Exception as e:
            return f"文件操作失败: {str(e)}"
    
    def _validate_path(self, file_path: str) -> Union[Path, None]:
        """验证文件路径的安全性"""
        try:
            # 转换为绝对路径
            path = Path(file_path)
            if not path.is_absolute():
                path = self.base_path / path
            
            path = path.resolve()
            
            # 检查是否在允许的基础路径内
            try:
                path.relative_to(self.base_path)
            except ValueError:
                return None  # 路径在基础路径外
            
            # 检查是否为禁止的路径
            path_str = str(path)
            for forbidden in self.forbidden_paths:
                if path_str.startswith(forbidden):
                    return None
            
            return path
            
        except Exception:
            return None
    
    async def _read_file(self, file_path: Path, encoding: str) -> str:
        """读取文件内容"""
        if not file_path.exists():
            return f"错误: 文件不存在: {file_path}"
        
        if not file_path.is_file():
            return f"错误: 路径不是文件: {file_path}"
        
        try:
            with open(file_path, 'r', encoding=encoding) as f:
                content = f.read()
            
            return f"文件内容 ({len(content)} 字符):\n\n{content}"
            
        except Exception as e:
            return f"读取文件失败: {str(e)}"
    
    async def _write_file(self, file_path: Path, content: str, encoding: str, overwrite: bool) -> str:
        """写入文件"""
        if file_path.exists() and not overwrite:
            return f"错误: 文件已存在: {file_path}"
        
        file_path.parent.mkdir(parents=True, exist_ok=True)
        
        try:
            with open(file_path, 'w', encoding=encoding) as f:
                f.write(content)
            
            return f"✅ 文件操作成功: {file_path}"
            
        except Exception as e:
            return f"写入文件失败: {str(e)}"
    
    async def _delete_file(self, file_path: Path) -> str:
        """删除文件"""
        if not file_path.exists():
            return f"错误: 文件不存在: {file_path}"
        
        try:
            file_path.unlink()
            return f"✅ 删除文件成功: {file_path}"
            
        except Exception as e:
            return f"删除文件失败: {str(e)}"
    
    async def _list_directory(self, dir_path: Path) -> str:
        """列出目录内容"""
        if not dir_path.exists():
            return f"错误: 目录不存在: {dir_path}"
        
        try:
            items = []
            for item in sorted(dir_path.iterdir()):
                item_type = "📁" if item.is_dir() else "📄"
                items.append(f"{item_type} {item.name}")
            
            return f"目录内容:\n" + "\n".join(items) if items else "目录为空"
            
        except Exception as e:
            return f"列出目录失败: {str(e)}"
    
    async def _check_exists(self, file_path: Path) -> str:
        """检查文件或目录是否存在"""
        if file_path.exists():
            return f"✅ 路径存在: {file_path}"
        else:
            return f"❌ 路径不存在: {file_path}"


# 创建工具实例并注册到默认注册表
def register_filesystem_tool():
    """注册文件系统工具"""
    from .base import default_registry
    fs_tool = FileSystemTool()
    default_registry.register(fs_tool)
    return fs_tool

# 自动注册
register_filesystem_tool()